/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package doxy;

import global.DoxyApp;
import global.MyVector;
import japa.parser.JavaParser;
import japa.parser.ParseException;
import japa.parser.ast.Comment;
import japa.parser.ast.CompilationUnit;
import kit.FileKit;
import kit.UIKit;

import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.beans.PropertyVetoException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import kit.ServerKit;

/**
 *
 * @author Rendra
 */
public class Main extends javax.swing.JFrame {
    
    private String dox = "javadoc";
    private String projectFolder;
    private String projectName;
    private DefaultMutableTreeNode rootNode;
    private DefaultTreeModel treeModel;
    private MyVector myVector;
    private List<String> recentProjects = new ArrayList<>();
    private String recentFile;
    private String baseOutputDir = "D:/Result/";
    
    /**
     * Creates new form Main
     */
    public Main() {
        initComponents();
        setIconImage(new ImageIcon(getClass().getResource("/assets/doxy-app.png")).getImage());
        
        recentFile = getClass().getResource("/global/recent.txt").getPath();
        recentFile = recentFile.substring(1);
        recentFile = recentFile.replace("%20", " ");
        
        customizeUI();
        openMainImage();
        getRecentItems();
    }
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        MyToolbar = new javax.swing.JToolBar();
        TOpenProject = new javax.swing.JToggleButton();
        TRunProject = new javax.swing.JToggleButton();
        TSaveProject = new javax.swing.JToggleButton();
        MySplit = new javax.swing.JSplitPane();
        LeftSide = new javax.swing.JTabbedPane();
        TabExplorerProject = new javax.swing.JPanel();
        TreeScroll = new javax.swing.JScrollPane();
        MyTree = new javax.swing.JTree();
        TabRecentProject = new javax.swing.JPanel();
        RecentScroll = new javax.swing.JScrollPane();
        ListRecentProjects = new javax.swing.JList();
        RightSide = new javax.swing.JPanel();
        MyDesktopPane = new javax.swing.JDesktopPane();
        StatusPanel = new javax.swing.JPanel();
        LblTime = new javax.swing.JLabel();
        LblCampus = new javax.swing.JLabel();
        MainMenu = new javax.swing.JMenuBar();
        MProject = new javax.swing.JMenu();
        MILoadProject = new javax.swing.JMenuItem();
        MSepProject = new javax.swing.JPopupMenu.Separator();
        MFile = new javax.swing.JMenu();
        MIParseFile = new javax.swing.JMenuItem();
        MIParseTranslate = new javax.swing.JMenuItem();
        MSepFile = new javax.swing.JPopupMenu.Separator();
        MIRunProject = new javax.swing.JMenuItem();
        MGenDocs = new javax.swing.JMenu();
        MIIndonesian = new javax.swing.JMenuItem();
        MIEnglish = new javax.swing.JMenuItem();
        MISaveProject = new javax.swing.JMenuItem();
        MSepExit = new javax.swing.JPopupMenu.Separator();
        MIExit = new javax.swing.JMenuItem();
        MHelp = new javax.swing.JMenu();
        MIHowTo = new javax.swing.JMenuItem();
        MICheckUpdate = new javax.swing.JMenuItem();
        MIAbout = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Doxy - Make Your Project Documentation Sexy");
        setName("MainFrame"); // NOI18N
        setResizable(false);

        MyToolbar.setFloatable(false);
        MyToolbar.setRollover(true);

        TOpenProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/load_project_big.png"))); // NOI18N
        TOpenProject.setToolTipText("Load Project");
        TOpenProject.setFocusable(false);
        TOpenProject.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        TOpenProject.setMargin(new java.awt.Insets(2, 4, 2, 4));
        TOpenProject.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        TOpenProject.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                TOpenProjectActionPerformed(evt);
            }
        });
        MyToolbar.add(TOpenProject);

        TRunProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/run_project_big.png"))); // NOI18N
        TRunProject.setToolTipText("Generate Docs");
        TRunProject.setEnabled(false);
        TRunProject.setFocusable(false);
        TRunProject.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        TRunProject.setMargin(new java.awt.Insets(2, 4, 2, 4));
        TRunProject.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        TRunProject.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                TRunProjectActionPerformed(evt);
            }
        });
        MyToolbar.add(TRunProject);

        TSaveProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/save_as big.png"))); // NOI18N
        TSaveProject.setToolTipText("Save Project As");
        TSaveProject.setEnabled(false);
        TSaveProject.setFocusable(false);
        TSaveProject.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        TSaveProject.setMargin(new java.awt.Insets(2, 4, 2, 4));
        TSaveProject.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        TSaveProject.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                TSaveProjectActionPerformed(evt);
            }
        });
        MyToolbar.add(TSaveProject);

        MySplit.setBorder(null);
        MySplit.setDividerLocation(230);
        MySplit.setDividerSize(3);

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        MyTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        MyTree.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                MyTreeMouseClicked(evt);
            }
        });
        TreeScroll.setViewportView(MyTree);

        javax.swing.GroupLayout TabExplorerProjectLayout = new javax.swing.GroupLayout(TabExplorerProject);
        TabExplorerProject.setLayout(TabExplorerProjectLayout);
        TabExplorerProjectLayout.setHorizontalGroup(
            TabExplorerProjectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(TreeScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 225, Short.MAX_VALUE)
        );
        TabExplorerProjectLayout.setVerticalGroup(
            TabExplorerProjectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(TreeScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 419, Short.MAX_VALUE)
        );

        LeftSide.addTab("Project Explorer", TabExplorerProject);

        ListRecentProjects.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                ListRecentProjectsMouseClicked(evt);
            }
        });
        RecentScroll.setViewportView(ListRecentProjects);

        javax.swing.GroupLayout TabRecentProjectLayout = new javax.swing.GroupLayout(TabRecentProject);
        TabRecentProject.setLayout(TabRecentProjectLayout);
        TabRecentProjectLayout.setHorizontalGroup(
            TabRecentProjectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(RecentScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 225, Short.MAX_VALUE)
        );
        TabRecentProjectLayout.setVerticalGroup(
            TabRecentProjectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(RecentScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 419, Short.MAX_VALUE)
        );

        LeftSide.addTab("Recent Projects", TabRecentProject);

        MySplit.setLeftComponent(LeftSide);

        MyDesktopPane.setBackground(new java.awt.Color(240, 240, 240));

        javax.swing.GroupLayout RightSideLayout = new javax.swing.GroupLayout(RightSide);
        RightSide.setLayout(RightSideLayout);
        RightSideLayout.setHorizontalGroup(
            RightSideLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(MyDesktopPane, javax.swing.GroupLayout.DEFAULT_SIZE, 567, Short.MAX_VALUE)
        );
        RightSideLayout.setVerticalGroup(
            RightSideLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(MyDesktopPane, javax.swing.GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE)
        );

        MySplit.setRightComponent(RightSide);

        StatusPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        LblTime.setText("...");

        LblCampus.setText("Adhi Tama Surabaya Institute Of Technology");

        javax.swing.GroupLayout StatusPanelLayout = new javax.swing.GroupLayout(StatusPanel);
        StatusPanel.setLayout(StatusPanelLayout);
        StatusPanelLayout.setHorizontalGroup(
            StatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, StatusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(LblCampus)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(LblTime)
                .addContainerGap())
        );
        StatusPanelLayout.setVerticalGroup(
            StatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(StatusPanelLayout.createSequentialGroup()
                .addGroup(StatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(LblTime)
                    .addComponent(LblCampus))
                .addGap(0, 11, Short.MAX_VALUE))
        );

        MProject.setText("Project");

        MILoadProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/load_project.png"))); // NOI18N
        MILoadProject.setText("Load Project");
        MILoadProject.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MILoadProjectActionPerformed(evt);
            }
        });
        MProject.add(MILoadProject);
        MProject.add(MSepProject);

        MFile.setText("File");

        MIParseFile.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/parse_file.png"))); // NOI18N
        MIParseFile.setText("Parse File");
        MIParseFile.setEnabled(false);
        MIParseFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MIParseFileActionPerformed(evt);
            }
        });
        MFile.add(MIParseFile);

        MIParseTranslate.setText("Translate Comments");
        MIParseTranslate.setEnabled(false);
        MIParseTranslate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MIParseTranslateActionPerformed(evt);
            }
        });
        MFile.add(MIParseTranslate);

        MProject.add(MFile);
        MProject.add(MSepFile);

        MIRunProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/run_project.png"))); // NOI18N
        MIRunProject.setText("Translate Project");
        MIRunProject.setEnabled(false);
        MIRunProject.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MIRunProjectActionPerformed(evt);
            }
        });
        MProject.add(MIRunProject);

        MGenDocs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/generate_doc.png"))); // NOI18N
        MGenDocs.setText("Generate Documentation");

        MIIndonesian.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/indonesia.png"))); // NOI18N
        MIIndonesian.setText("Indonesian");
        MIIndonesian.setEnabled(false);
        MIIndonesian.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MIIndonesianActionPerformed(evt);
            }
        });
        MGenDocs.add(MIIndonesian);

        MIEnglish.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/england.png"))); // NOI18N
        MIEnglish.setText("English");
        MIEnglish.setEnabled(false);
        MIEnglish.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MIEnglishActionPerformed(evt);
            }
        });
        MGenDocs.add(MIEnglish);

        MProject.add(MGenDocs);

        MISaveProject.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/save_as.png"))); // NOI18N
        MISaveProject.setText("Save Project");
        MISaveProject.setEnabled(false);
        MISaveProject.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MISaveProjectActionPerformed(evt);
            }
        });
        MProject.add(MISaveProject);
        MProject.add(MSepExit);

        MIExit.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/exit.png"))); // NOI18N
        MIExit.setText("Exit");
        MIExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MIExitActionPerformed(evt);
            }
        });
        MProject.add(MIExit);

        MainMenu.add(MProject);

        MHelp.setText("Help");

        MIHowTo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/support.png"))); // NOI18N
        MIHowTo.setText("How To Use");
        MIHowTo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MIHowToActionPerformed(evt);
            }
        });
        MHelp.add(MIHowTo);

        MICheckUpdate.setText("Check For Update");
        MICheckUpdate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MICheckUpdateActionPerformed(evt);
            }
        });
        MHelp.add(MICheckUpdate);

        MIAbout.setIcon(new javax.swing.ImageIcon(getClass().getResource("/assets/about.png"))); // NOI18N
        MIAbout.setText("About");
        MIAbout.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                MIAboutActionPerformed(evt);
            }
        });
        MHelp.add(MIAbout);

        MainMenu.add(MHelp);

        setJMenuBar(MainMenu);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(MyToolbar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(MySplit)
            .addComponent(StatusPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(MyToolbar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(MySplit, javax.swing.GroupLayout.PREFERRED_SIZE, 447, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(StatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );

        pack();
        setLocationRelativeTo(null);
    }// </editor-fold>//GEN-END:initComponents

    private void MILoadProjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MILoadProjectActionPerformed
        // TODO add your handling code here:
        JFileChooser chooser;
        String choosertitle = "Choose a Root Project Directory";
        chooser = new JFileChooser();
        chooser.setCurrentDirectory(new java.io.File(DoxyApp.bridge.getLastPath()));
        chooser.setDialogTitle(choosertitle);
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        chooser.setAcceptAllFileFilterUsed(false);
        if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            projectFolder = chooser.getSelectedFile().getAbsolutePath();
            DoxyApp.bridge.setLastPath(projectFolder);
            DoxyApp.bridge.setFromRecent(false);
            drawSrcTree();
        }
    }//GEN-LAST:event_MILoadProjectActionPerformed

    private void TOpenProjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_TOpenProjectActionPerformed
        // TODO add your handling code here:
        MILoadProjectActionPerformed(evt);
    }//GEN-LAST:event_TOpenProjectActionPerformed

    private void MIExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MIExitActionPerformed
        // TODO add your handling code here:
        try {            
            Thread.sleep(200);
        } catch (InterruptedException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.exit(1);
    }//GEN-LAST:event_MIExitActionPerformed

    private void MIRunProjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MIRunProjectActionPerformed
        String baseWorkingDir = baseOutputDir+projectName;
        /**
         * Create first list file
         * List all original source code
         */
        MyVector allFiles = DoxyApp.bridge.getListSources();
        try {
            File srcLst = new File(baseWorkingDir+"/src.lst");
            if (!srcLst.exists()) {
                srcLst.createNewFile();
                FileKit.writeTextFile(allFiles, baseWorkingDir+"/src.lst");
            }
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        String baseDirDst   = baseWorkingDir+"/docs/temp/";
        String flagFileName = baseWorkingDir+"/docs/temp/translated.txt";
        String ndFileList   = baseWorkingDir+"/src.ind.lst";
        File nwFile = new File(ndFileList);
        
        if (!nwFile.exists()) {
            /**
             * Copying original source code into temp folder
             * for Indonesian translation
             */
            for (int i=0;i<allFiles.size();i++) {
                String pathFile = allFiles.get(i).toString();
                File src = new File(pathFile);
                String [] splitSrcPath = pathFile.replaceAll("\\\\", "/").split("/");
                File dst = new File(baseDirDst+splitSrcPath[splitSrcPath.length-1]); 
                try {
                    File dirDst = new File(baseDirDst);
                    if (dirDst.listFiles().length <= allFiles.size()) {
                        FileKit.copyFolder(src, dst);
                    }
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

            /**
             * List all files in temp folder & translate those files
             */ 
            try {
                MyVector tempFiles = FileKit.getFileDirectory(new File(baseDirDst), ".java");
                if (!nwFile.exists()) {
                    nwFile.createNewFile();
                    FileKit.writeTextFile(tempFiles, ndFileList);
                }

                File flagFile = new File(flagFileName);
                if (!flagFile.exists()) {
                    new TranslateProject(tempFiles).execute();
                } else {
                    new Translated().execute();
                }
            } catch (IOException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            } catch (Exception ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            new Translated().execute();
        }
    }//GEN-LAST:event_MIRunProjectActionPerformed

    private void MIParseFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MIParseFileActionPerformed
        // TODO add your handling code here:
        clearDesktopPane();
        FrmSrcList frameSrc = new FrmSrcList(this, true);
        frameSrc.setVisible(true);
        
        if (DoxyApp.bridge.isFileChoosen()) {
            try {
                FrmParseFile frmParse = new FrmParseFile();
                MyDesktopPane.add(frmParse);
                frmParse.setVisible(true);
                frmParse.setBorder(null);
                try {
                    frmParse.setMaximum(true);
                    ((javax.swing.plaf.basic.BasicInternalFrameUI)frmParse.getUI()).setNorthPane(null);
                } catch (PropertyVetoException pvx) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, pvx);
                }
            } catch (FileNotFoundException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ParseException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_MIParseFileActionPerformed

    private void MIParseTranslateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MIParseTranslateActionPerformed
        // TODO add your handling code here:
        clearDesktopPane();
        FrmSrcList frameSrc = new FrmSrcList(this, true);
        frameSrc.setVisible(true);
        
        try {
            if (DoxyApp.bridge.isFileChoosen()) {
                FrmParseTranslate frmParse = new FrmParseTranslate();
                MyDesktopPane.add(frmParse);
                frmParse.setVisible(true);
                frmParse.setBorder(null);
                try {
                    frmParse.setMaximum(true);
                    ((javax.swing.plaf.basic.BasicInternalFrameUI)frmParse.getUI()).setNorthPane(null);
                } catch (PropertyVetoException pvx) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, pvx);
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//GEN-LAST:event_MIParseTranslateActionPerformed

    private void ListRecentProjectsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_ListRecentProjectsMouseClicked
        // TODO add your handling code here:
        if (evt.getClickCount()==2) {
            projectFolder = ListRecentProjects.getSelectedValue().toString();
            DoxyApp.bridge.setFromRecent(true);
            drawSrcTree();
            LeftSide.setSelectedIndex(0);
        }
    }//GEN-LAST:event_ListRecentProjectsMouseClicked

    private void TRunProjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_TRunProjectActionPerformed
        // TODO add your handling code here:
        MIRunProjectActionPerformed(evt);
    }//GEN-LAST:event_TRunProjectActionPerformed

    private void MIHowToActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MIHowToActionPerformed
        // TODO add your handling code here:
        ServerKit.openURL(DoxyApp.myWiki);
    }//GEN-LAST:event_MIHowToActionPerformed

    private void MICheckUpdateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MICheckUpdateActionPerformed
        // TODO add your handling code here:
        new FrmVersion(this, true).setVisible(true);
    }//GEN-LAST:event_MICheckUpdateActionPerformed

    private void MIAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MIAboutActionPerformed
        // TODO add your handling code here:
        new FrmAbout(this, true).setVisible(true);
    }//GEN-LAST:event_MIAboutActionPerformed

    private void MyTreeMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_MyTreeMouseClicked
        // TODO add your handling code here:
        if (evt.getClickCount()==2) {
            TreePath tp = MyTree.getPathForLocation(evt.getX(), evt.getY());
            if (tp != null) {
                try {
                    String fullPath = tp.toString().replace("[", "").replace(" ", "");
                    fullPath = fullPath.replace("]", "");
                    fullPath = fullPath.replace(",", "\\");
                    DoxyApp.bridge.setSelectedSrcFile(fullPath);
                    
                    clearDesktopPane();
                    FrmParseFile frmParse = new FrmParseFile();
                    MyDesktopPane.add(frmParse);
                    frmParse.setVisible(true);
                    frmParse.setBorder(null);
                    try {
                        frmParse.setMaximum(true);
                        ((javax.swing.plaf.basic.BasicInternalFrameUI)frmParse.getUI()).setNorthPane(null);
                    } catch (PropertyVetoException pvx) {
                        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, pvx);
                    }
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ParseException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }//GEN-LAST:event_MyTreeMouseClicked

    private void MIIndonesianActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MIIndonesianActionPerformed
        // TODO add your handling code here:
        generateDocs("indonesian");
    }//GEN-LAST:event_MIIndonesianActionPerformed

    private void MIEnglishActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MIEnglishActionPerformed
        // TODO add your handling code here:
        String baseWorkingDir = baseOutputDir+projectName;
        /**
         * Create first list file
         * List all original source code
         */
        MyVector allFiles = DoxyApp.bridge.getListSources();
        try {
            File srcLst = new File(baseWorkingDir+"/src.lst");
            if (!srcLst.exists()) {
                srcLst.createNewFile();
                FileKit.writeTextFile(allFiles, baseWorkingDir+"/src.lst");
            }
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        generateDocs("english");
    }//GEN-LAST:event_MIEnglishActionPerformed

    private void TSaveProjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_TSaveProjectActionPerformed
        // TODO add your handling code here:
        MISaveProjectActionPerformed(evt);
    }//GEN-LAST:event_TSaveProjectActionPerformed

    private void MISaveProjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MISaveProjectActionPerformed
        // TODO add your handling code here:
        JOptionPane.showMessageDialog(null, "The project successfully saved in "+
                    baseOutputDir+projectName, "Information", JOptionPane.INFORMATION_MESSAGE);
    }//GEN-LAST:event_MISaveProjectActionPerformed

    private void generateDocs(String lang) {
        String fileListName = "src.ind.lst";
        if (lang.equals("english")) {
            fileListName    = "src.lst";
        }
        String outputDocDir = "docs/"+lang;
        String workingDir   = baseOutputDir+projectName;
        try {
            File checkingDir = new File(workingDir+"/"+outputDocDir);
            if (checkingDir.listFiles().length <= 0) {
                String[] cmd = {
                    dox, 
                    "-docletpath", DoxyApp.doxletpath, 
                    "-doclet", DoxyApp.doxlet,
                    "-generatesources",
                    "-parsecomments",
                    "-title", DoxyApp.myAppName, 
                    "-hdf", "project.name", projectName, 
                    "-XDignore.symbol.file", 
                    "-d", workingDir+"/"+outputDocDir, 
                    "@"+workingDir+"/"+fileListName
                };
                Runtime.getRuntime().exec(cmd);
            }
            
            // Wait
            try {
                Thread.sleep(2500);
            } catch (InterruptedException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            JOptionPane.showMessageDialog(null, "Docs of this project created successfully."+
                    "\nCheck docs in "+workingDir+"/"+outputDocDir, "Information", 
                    JOptionPane.INFORMATION_MESSAGE);
            
            // Wait more
            try {
                Thread.sleep(2500);
            } catch (InterruptedException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void openMainImage() {
        clearDesktopPane();
        FrmMain frmMain = new FrmMain();
        MyDesktopPane.add(frmMain);
        frmMain.setVisible(true);
        frmMain.setBorder(null);
        try {
            frmMain.setMaximum(true);
            ((javax.swing.plaf.basic.BasicInternalFrameUI)frmMain.getUI()).setNorthPane(null);
        } catch (PropertyVetoException pvx) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, pvx);
        }
    }
    
    /**
     * Customize GUI :
     * Set root node of the tree disappear if no project selected
     * Set padding the components
     * Create top border of the status panel (bottom panel)
     */
    private void customizeUI(){
        LblTime.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
        LblCampus.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
        showDateTime();
        MyTree.setRootVisible(false);
        UIKit.flattenSplitPane(MySplit);
        
        // Set the left side panel width to static when frame resized
        this.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                MySplit.setDividerLocation(200);
            }
        });
        
        // Set padding the split pane
        LeftSide.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 0));
        RightSide.setBorder(BorderFactory.createEmptyBorder(0, 3, 3, 3));
        MyDesktopPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
        MyToolbar.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
        ListRecentProjects.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
        RecentScroll.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
        MyTree.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
        TabExplorerProject.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        // Create top border the status panel
        StatusPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.GRAY));
    }
    
    /*
     * Clear the desktop pane from loaded JInternalFrame
     */
    private void clearDesktopPane(){
        MyDesktopPane.removeAll();
        MyDesktopPane.repaint();
    }
    
    /**
     * Enable / disable components (MenuItem & ToogleButtons)
     * 
     * @param enable 
     */
    private void enableMenuItems(boolean enable){
        MIRunProject.setEnabled(enable);
        MIParseFile.setEnabled(enable);
        MIParseTranslate.setEnabled(enable);
        MISaveProject.setEnabled(enable);
        MIIndonesian.setEnabled(true);
        MIEnglish.setEnabled(true);
        
        TRunProject.setEnabled(enable);
        TSaveProject.setEnabled(enable);
    }
    
    private void getRecentItems() {
        try {
            if (recentFile.startsWith("ile")) {
                recentFile = recentFile.substring(5);
            }
            recentProjects = FileKit.readTextFile(recentFile);
            Vector<String> recentItems = new Vector<>();
            if (recentProjects.size()>0) {
                recentItems.addAll(recentProjects);
                ListRecentProjects.setListData(recentItems);
            }
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void addRecentItems() {
        if(recentProjects.size()==10) {
            recentProjects.remove(recentProjects.size()-1);
        }
        try {
            List<String> newItem = new ArrayList<>();
            newItem.add(projectFolder);
            clearDuplicateRecent();
            newItem.addAll(recentProjects);
            FileKit.writeTextFile(newItem, recentFile);
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void clearDuplicateRecent() {
        Iterator<String> itr = recentProjects.iterator();
        while (itr.hasNext()) {
            String old = itr.next();
            if (old.equals(projectFolder)) {
                itr.remove();
            }
        }
    }
    
    private class CopySource extends SwingWorker<String, String> {
        private final JLabel label = new JLabel("  Please wait ...", 
                new ImageIcon(this.getClass().getResource("/assets/loading.gif")), 
                SwingConstants.TRAILING);
        private final JPanel panel;
        private final JDialog dialog;
        
        public CopySource() {
            panel = new JPanel();
            dialog = new JDialog();
            dialog.setUndecorated(true);
            label.setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30));
            panel.setBorder(BorderFactory.createLineBorder(new Color(189, 199, 216), 1));
            panel.setBackground(new Color(237, 239, 244));
            panel.setLayout(new GridBagLayout());
            panel.add(label);
            dialog.add(panel);
            dialog.pack();
            dialog.setLocationRelativeTo(null);
            dialog.setVisible(true);
        }
        
        @Override
        protected String doInBackground() throws Exception {
            Thread.sleep(700);
            publish("  Setting up ...");
            
            File srcDir = new File(projectFolder);
            File dstDir = new File(baseOutputDir+projectName);
            try{
                FileKit.copyFolder(srcDir, dstDir);
                
                // Create Indonesian & English folder
                new File(baseOutputDir+projectName+"/docs").mkdir();
                new File(baseOutputDir+projectName+"/docs/temp").mkdir();
                new File(baseOutputDir+projectName+"/docs/indonesian").mkdir();
                new File(baseOutputDir+projectName+"/docs/english").mkdir();
                
                // Rewrite opened project
                projectFolder = baseOutputDir+projectName;
            }catch(IOException e){ }
            
            publish("  Done");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ix) { }
            return null;
        }        
        
        @Override
        protected void process(List<String> chunks) {
            label.setText(chunks.get(0));
            dialog.pack();
            dialog.setLocationRelativeTo(null);
            dialog.repaint();
        }

        @Override
        protected void done() {
            dialog.setVisible(false);
        }
    }
    
    private void drawSrcTree() {
        String [] splitPath = (projectFolder.replaceAll("\\\\", "/")).split("/");
        projectName = splitPath[splitPath.length-1];
        
        if (!DoxyApp.bridge.isFromRecent()) {
            new CopySource().execute();
        }
        DoxyApp.workPath = projectFolder;
            
        // Set JTree directory browser
        MyTree.setRootVisible(true);
        File file = new File(projectFolder);
        rootNode = new DefaultMutableTreeNode(file.getAbsolutePath());
        treeModel = new DefaultTreeModel(rootNode);
        MyTree.setModel(treeModel);
        
        myVector = FileKit.getFileDirectory(file);
        JTree.DynamicUtilTreeNode.createChildren(rootNode, myVector);

        // Set sub icon JTree
        Icon srcIcon = new ImageIcon(getClass().getResource("/assets/file_extension_jar.png"));
        MyTree.setCellRenderer(new DefaultTreeCellRenderer(){
            @Override
            public Component getTreeCellRendererComponent(final JTree tree, Object value, boolean sel,
                    boolean expanded, boolean leaf, int row, boolean hasFocus){
                JLabel label = (JLabel)super.getTreeCellRendererComponent(tree, value, sel, 
                        expanded, leaf, row, hasFocus);  
              if(((DefaultMutableTreeNode)value).isRoot())
                  label.setIcon(new ImageIcon(getClass().getResource("/assets/application.png")));
              return label;  
            } 
        });
        DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) MyTree.getCellRenderer();
        renderer.setLeafIcon(srcIcon);
        MyTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

        for (int i=0;i<MyTree.getRowCount();i++) {  
            MyTree.expandRow(i);  
        } 
        enableMenuItems(true);
        addRecentItems();
    }
    
    private void showDateTime() {
        final DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        int timeDelay = 1000;
        ActionListener time;
        time = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                Calendar now = Calendar.getInstance();                
                LblTime.setText("Current time : " + dateFormat.format(now.getTime()));
            }
        };
        new Timer(timeDelay, time).start();
    }
    
    private class TranslateProject extends SwingWorker<String, String> {
        private final JLabel label = new JLabel("  Please wait ...", 
                new ImageIcon(this.getClass().getResource("/assets/loading.gif")), 
                SwingConstants.TRAILING);
        private final JPanel panel;
        private final JDialog dialog;
        private final MyVector filesTemp;
        
        public TranslateProject(MyVector tempFiles) {
            filesTemp = tempFiles;
            dialog = new JDialog();
            panel = new JPanel();
            dialog.setUndecorated(true);
            label.setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30));
            panel.setBorder(BorderFactory.createLineBorder(new Color(189, 199, 216), 1));
            panel.setBackground(new Color(237, 239, 244));
            panel.setLayout(new GridBagLayout());
            panel.add(label);
            dialog.add(panel);
            dialog.pack();
            dialog.setLocationRelativeTo(null);
            dialog.setVisible(true);
        }
        
        @Override
        protected String doInBackground() throws Exception {
            publish("  Translating ...");
            try {
                Thread.sleep(700);
            } catch (InterruptedException ix) { }

            for (int i=0;i<filesTemp.size();i++) {
                // Starting process
                String slctdFile = filesTemp.get(i).toString();
                publish("  Processing "+slctdFile);
                
                FileInputStream in = new FileInputStream(slctdFile);
                CompilationUnit comp;
                try {
                    comp = JavaParser.parse(in);
                } finally {
                    in.close();
                }
                Pattern p_c = Pattern.compile(DoxyApp.rxComment, Pattern.DOTALL);
                Matcher m_c = p_c.matcher(comp.toString());
                if (m_c.find()) {
                    List<Comment> srcComments = comp.getComments();
                    int j = 0;
                    for (Comment cm : srcComments){
                        String [] contents = cm.getContent().split("\n");
                        StringBuilder bContent = FileKit.extractAndTranslate(contents);
                        cm.setContent(bContent.toString());
                        srcComments.set(j, cm);
                        j++;
                    }
                    comp.setComments(srcComments);
                    FileKit.writeTextFile(comp.toString(), slctdFile);
                }
            }
            
            String flagFileName = baseOutputDir+projectName+"/docs/temp/translated.txt";
            File flagFile = new File(flagFileName);
            if (!flagFile.exists())
                flagFile.createNewFile();
            FileKit.writeTextFile("true", flagFileName);
            
            publish("  Done");
            try {
                Thread.sleep(1500);
            } catch (InterruptedException ix) { }
            return null;
        }

        @Override
        protected void process(List<String> chunks) {
            label.setText(chunks.get(0));
            dialog.pack();
            dialog.setLocationRelativeTo(null);
            dialog.repaint();
        }

        @Override
        protected void done() {
            dialog.setVisible(false);
        }
    }
    
    private class Translated extends SwingWorker<String, String> {
        private final JLabel label = new JLabel("  Translating ...", 
                new ImageIcon(this.getClass().getResource("/assets/loading.gif")), 
                SwingConstants.TRAILING);
        private final JPanel panel;
        private final JDialog dialog;
        
        public Translated() {
            dialog = new JDialog();
            panel = new JPanel();
            dialog.setUndecorated(true);
            label.setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30));
            panel.setBorder(BorderFactory.createLineBorder(new Color(189, 199, 216), 1));
            panel.setBackground(new Color(237, 239, 244));
            panel.setLayout(new GridBagLayout());
            panel.add(label);
            dialog.add(panel);
            dialog.pack();
            dialog.setLocationRelativeTo(null);
            dialog.setVisible(true);
        }
        
        @Override
        protected String doInBackground() throws Exception {
            try {
                Thread.sleep(4000);
            } catch (InterruptedException ix) { }
            
            publish("  Done");
            try {
                Thread.sleep(1500);
            } catch (InterruptedException ix) { }
            return null;
        }
        
        @Override
        protected void process(List<String> chunks) {
            label.setText(chunks.get(0));
            dialog.pack();
            dialog.setLocationRelativeTo(null);
            dialog.repaint();
        }

        @Override
        protected void done() {
            dialog.setVisible(false);
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel LblCampus;
    private javax.swing.JLabel LblTime;
    private javax.swing.JTabbedPane LeftSide;
    private javax.swing.JList ListRecentProjects;
    private javax.swing.JMenu MFile;
    private javax.swing.JMenu MGenDocs;
    private javax.swing.JMenu MHelp;
    private javax.swing.JMenuItem MIAbout;
    private javax.swing.JMenuItem MICheckUpdate;
    private javax.swing.JMenuItem MIEnglish;
    private javax.swing.JMenuItem MIExit;
    private javax.swing.JMenuItem MIHowTo;
    private javax.swing.JMenuItem MIIndonesian;
    private javax.swing.JMenuItem MILoadProject;
    private javax.swing.JMenuItem MIParseFile;
    private javax.swing.JMenuItem MIParseTranslate;
    private javax.swing.JMenuItem MIRunProject;
    private javax.swing.JMenuItem MISaveProject;
    private javax.swing.JMenu MProject;
    private javax.swing.JPopupMenu.Separator MSepExit;
    private javax.swing.JPopupMenu.Separator MSepFile;
    private javax.swing.JPopupMenu.Separator MSepProject;
    private javax.swing.JMenuBar MainMenu;
    private javax.swing.JDesktopPane MyDesktopPane;
    private javax.swing.JSplitPane MySplit;
    private javax.swing.JToolBar MyToolbar;
    private javax.swing.JTree MyTree;
    private javax.swing.JScrollPane RecentScroll;
    private javax.swing.JPanel RightSide;
    private javax.swing.JPanel StatusPanel;
    private javax.swing.JToggleButton TOpenProject;
    private javax.swing.JToggleButton TRunProject;
    private javax.swing.JToggleButton TSaveProject;
    private javax.swing.JPanel TabExplorerProject;
    private javax.swing.JPanel TabRecentProject;
    private javax.swing.JScrollPane TreeScroll;
    // End of variables declaration//GEN-END:variables
}
